package com.molichuxing.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

import javax.annotation.Resource;

import com.molichuxing.entity.ViolationUnableDto;
import com.molichuxing.entity.ViolationUnableKeyCustomersDto;
import com.molichuxing.entity.ViolationUntreatedDto;
import com.molichuxing.entity.ViolationUntreatedKeyCustomersDto;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.PoiExcelUtils;
import com.molichuxing.services.business.dto.response.*;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.CollectionUtils;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.DingTalkUtil;
import com.molichuxing.service.CarViolationJobService;
import com.molichuxing.services.business.service.CarBizService;
import com.molichuxing.services.business.service.ClxBizService;
import com.molichuxing.services.business.service.OrderBizService;
import com.molichuxing.services.business.service.SmsBizService;
import com.molichuxing.services.infrastructure.dto.request.create.MessageCenterCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.NotifyPushCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.ViolationCreateDto;

/**
 * @Author: renzhengyu
 * @Description:
 * @Date: Created in 11:33 2019/11/21
 * @Modified By:
 **/
@Service("carViolationJobService")
public class CarViolationJobServiceImpl implements CarViolationJobService {
    private static final Logger logger = LoggerFactory.getLogger(CarViolationJobServiceImpl.class);
    
    private static final String pushViolationRemind="push_violation_remind";
	private static final String instationViolationRemind="instation_violation_remind";
	private static final String dingTalkViolationUnableQuery="dingTalk_violation_unable_query";
	private static final String dingTalkViolationUntreated="dingTalk_violation_untreated";
    private static final String emailViolationUnableQuery="email_violation_unable_query";
    private static final String emailViolationUntreated="email_violation_untreated";

    @Resource
    private OrderReturnService orderReturnService;
    @Resource
    private CarViolationService carViolationService;
    @Resource
    private OrderBizService orderBizService;
    @Resource
    private CarBizService carBizService;
    @Resource
    private VehicleService vehicleService;
    @Resource
    private VehicleModleService vehicleModleService;
    @Resource
    private ClxBizService clxBizService;
    @Resource
    private StoreService storeService;
    @Resource
    private SmsBizService smsBizService;
	@Resource
	private MessageTemplateService messageTemplateService;
	@Resource
	private MessageCenterService messageCenterService;
	@Resource
	private NotifyPushService notifyPushService;
	@Resource
	private UserService userService;
    @Resource
    private RiskEmailService riskEmailService;
    @Resource
    private CarService carService;
	
	@Value("${dingTalk.violation.url}")
	private String dingTalkViolationUrl;

    @Value("${email.account}")
    private String emailAccount;

    @Value("${email.password}")
    private String emailPassword;


    private static final Integer VIOLATION_CODE = 1008;

    private static final Integer NO_VIOLATION_CODE = 1009;


    /**
     * 违章数据查询
     * @return
     */
    @Override
    public Boolean getCarViolationHandler() throws Exception {

        HashSet<Integer> carIdSet = new HashSet<>();

        //查询用车中车辆 查询两个订单表
        List<OrderCarInfoAppDto> orderCarInfoAppDtoList = orderBizService.getCarIdsByUser(null, OrderExclusivelStatusEnum.TRADE_USE.getValue());
        if(orderCarInfoAppDtoList == null || orderCarInfoAppDtoList.isEmpty()){
            logger.info("查询所有用车中的订单信息为空");
        }else {
            orderCarInfoAppDtoList.forEach(orderCarInfoAppDto -> {
                if (orderCarInfoAppDto.getCarId() != null && orderCarInfoAppDto.getCarId() > 0) {
                    carIdSet.add(orderCarInfoAppDto.getCarId());
                }
            });
        }
        //及当前请求时间-确认还车时间<=30日的车辆 查询还车表
        List<OrderReturnDto> orderReturnDtoList = orderReturnService.getOrderReturnDtoListByNow();
        if(orderReturnDtoList == null || orderReturnDtoList.isEmpty()){
            logger.info("查询还车信息为空");
        }else {
            orderReturnDtoList.forEach(orderReturnDto -> {
                if (orderReturnDto.getCarId() != null && orderReturnDto.getCarId() > 0) {
                    carIdSet.add(orderReturnDto.getCarId());
                }
            });
        }
        //及存在违章待处理和待缴费记录的车辆  查询违章表
        List<CarsViolationDto> carsViolationDtoList = carViolationService.getCarsViolationByStatus();
        if(carsViolationDtoList == null || carsViolationDtoList.isEmpty()){
            logger.info("查询违章信息为空");
        }else {
            carsViolationDtoList.forEach(carsViolationDto -> {
                if (carsViolationDto.getCarId() != null && carsViolationDto.getCarId() > 0) {
                    carIdSet.add(carsViolationDto.getCarId());
                }
            });
        }

        List<Integer> carIdList = new ArrayList<>(carIdSet);
        if(carIdList.size() <= 0){
            logger.info("暂无需要查询的车辆");
            return true;
        }

        //1违章无法查询isList
        List<ViolationUnableDto> unableQueryList= new ArrayList<>();
        //2违章未解决isList
        List<ViolationUntreatedDto> untreatedList= new ArrayList<>();
        //查询模板信息
        Map<String,MessageTemplateDto> dingAndEmailByKeys = getDingAndEmailByKeys();
        //有订单信息，但无符合条件的车辆
        Map<Integer,Object> carIdMap = new HashMap<>();

        //调用违章查询接口 返回违章接口信息List

        for (Integer carId:carIdList) {

            CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carId);
            if(null == carDetailBizDto){
                logger.error("查询车辆信息为空");
            }
            VehicleDto vehicleDto = vehicleService.getVehicleByVehicleId(carDetailBizDto.getVehicleId());
            if(null == vehicleDto){
                logger.error("查询车型信息为空");
            }
            VehicleModleDto vehicleModleDto = vehicleModleService.getVehicleModleDtoById(vehicleDto.getSeriesId());
            if(null == vehicleModleDto){
                logger.error("查询车型详细信息为空");
            }
            //查询车辆是否违章
            ResponseResult<List<ViolationBeanDto>> result = clxBizService.getCxyViolation(carDetailBizDto.getLicencePlate(),carDetailBizDto.getVin(),carDetailBizDto.getEngineCode());

            //状态码为1008表示有违章
            if(VIOLATION_CODE.equals(result.getCode())){
                // 根据车辆id查询所有对应的订单号
                List<CarOrderBizDto> carOrderBizDtoList = orderBizService.getOrderByCar(carId);

                //查询之前先把状态置为已处理已缴费
                carViolationService.modifyViolationStatusByCarId(carId);

                for (ViolationBeanDto violationBeanDto:result.getData()) {
                	 /**
                     * 查询该条违章是否 《标记为已缴费》 
                     * 标记为已缴费的 就不需要在按照第三方的状态，
                     * 默认按照已缴费 不用给用户发短信等信息
                     */
                    CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(null,carId,violationBeanDto.getRegulationTime());
                    if(null != carsViolationDto) {
                    	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
                    	if(CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
                    		continue;
                    	}
                    }
                	
                    if(CollectionUtils.isEmpty(carOrderBizDtoList)) {
                        // 保存违章信息 无订单信息的违章
                        violation(violationBeanDto,carDetailBizDto,null);
                        //违章未解决 无订单信息 数据组装
                        untreatedList.add(toViolationUntreatedDto(carDetailBizDto,violationBeanDto,null,null));
                        continue;
                    }
                    
                    
                    for (CarOrderBizDto carOrderBizDto : carOrderBizDtoList) {
                        if (null == carOrderBizDto.getDeliveryTime()) {
                            continue;
                        }
                        //违章时间 > 提车时间
                        if(violationBeanDto.getRegulationTime().isAfter(carOrderBizDto.getDeliveryTime())) {

                            //查询该订单的还车时间
                            OrderReturnDto orderReturnDto = orderReturnService.getOrderReturn(carOrderBizDto.getOrderCode());

                            //该订单未还车 或者 违章时间 < 还车时间
                            if(null == orderReturnDto || violationBeanDto.getRegulationTime().isBefore(orderReturnDto.getReturnTime())){
                                // 保存违章信息
                                violation(violationBeanDto,carDetailBizDto,carOrderBizDto);
                                //状态为待处理或待缴费发送提醒
                                if(!CarViolationEnum.NOT_RENT.getValue().equals(violationBeanDto.getStatus())){
                                    UserDto userDto = userService.getUser(carOrderBizDto.getUserId());
                                    if(null == userDto){
                                        logger.error("查询用户信息为空userId："+carOrderBizDto.getUserId());
                                        throw new Exception("查询用户信息为空userId："+carOrderBizDto.getUserId());
                                    }
                                    //发送短信
                                    sendNote(userDto.getPhone(),violationBeanDto);
                                    //推送和站内信
                                    sendPush(carOrderBizDto.getUserId(),userDto.getPhone(),violationBeanDto);

                                    //以邮件形式向客服人员发送违章未处理信息；
                                    //违章未解决 数据组装
                                    untreatedList.add(toViolationUntreatedDto(carDetailBizDto,violationBeanDto,carOrderBizDto,userDto));
                                }
                            }

                        }

                    }
                }

            }else if(NO_VIOLATION_CODE.equals(result.getCode())){
                //如果无违章  则验证本地库是否存在违章 ，如果存在则修改状态（改为违章已处理）
                carViolationService.modifyViolationStatusByCarId(carId);
            }else if(result.getCode().equals(1002) || result.getCode().equals(1006) || result.getCode().equals(1007) || result.getCode().equals(1010)){
                // 违章无法查询数据 数据组装
                // 根据车辆id查询所有对应的订单号
                List<CarOrderBizDto> carOrderBizDtoList = orderBizService.getOrderByCar(carId);

                if(null != carOrderBizDtoList && carOrderBizDtoList.size() > 0){
                    for (CarOrderBizDto carOrderBizDto : carOrderBizDtoList) {
                        if(null != carOrderBizDto.getLeaseInception() && null != carOrderBizDto.getLeaseExpire()
                                && LocalDate.now().isAfter(carOrderBizDto.getLeaseInception())
                                && LocalDate.now().isBefore(carOrderBizDto.getLeaseExpire()) ){
                            //起止时间内的订单，插入数据
                            unableQueryList.add(toViolationUnableDto(carDetailBizDto,carOrderBizDto));
                            carIdMap.put(carId,carId);
                        }
                    }
                }else {
                        unableQueryList.add(toViolationUnableDto(carDetailBizDto,null));
                }

                //有订单信息，但无符合条件的车辆
                if(null == carIdMap.get(carId)){
                    unableQueryList.add(toViolationUnableDto(carDetailBizDto,null));
                }


                //无法查询的车辆 查询违章表 算作违章未解决数据
                List<CarsViolationDto> carsUnableViolationDtoList =  carViolationService.getCarsViolationByCarId(carId);
                if(null != carsUnableViolationDtoList && carsUnableViolationDtoList.size() > 0){
                    for (CarsViolationDto carsUnableViolationDto:carsUnableViolationDtoList) {
                        if(!CarViolationEnum.NOT_RENT.getValue().equals(carsUnableViolationDto.getStatus().intValue())){
                            untreatedList.add(toViolationUntreatedDto(carDetailBizDto,carsUnableViolationDto));
                        }
                    }
                }



            }
        }
        if(unableQueryList.size() > 0){
            //违章无法查询数据 发送邮件
            sendUnableEmail(1,dingAndEmailByKeys,unableQueryList);
            //发送钉钉 违章无法查询数据
            sendDingTalk(1,dingAndEmailByKeys);
        }

        if(untreatedList.size() > 0){
            //违章未解决 发送邮件
            sendUntreatedEmail(2,dingAndEmailByKeys,untreatedList);
            //发送钉钉 违章无法查询数据
            sendDingTalk(2,dingAndEmailByKeys);
        }


        return true;
    }

    private void violation(ViolationBeanDto violationBeanDto,CarDetailBizDto carDetailBizDto,CarOrderBizDto carOrderBizDto) throws Exception {
        //根据用户id，车辆id，违章时间查询库中是否有数据
        CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(null,carDetailBizDto.getCarId(),violationBeanDto.getRegulationTime());
        if(null == carsViolationDto){
            //如果没数据，则新建违章表
            createViolation(carOrderBizDto,violationBeanDto,carDetailBizDto);
        }else{
            //如果有数据，判断当前违章状态是否与库中一致，不一致则更新数据库
        	Integer status = Integer.valueOf(carsViolationDto.getStatus());
        	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
        	if(!CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
        		if(!status.equals(violationBeanDto.getStatus())){
                    updateViolationById(carsViolationDto,violationBeanDto);
                }
        	}
            
        }
    }

    /**
     * 创建违章
     * @param carOrderBizDto
     * @param violationBeanDto
     * @param carDetailBizDto
     * @return
     * @throws Exception
     */
    private void createViolation(CarOrderBizDto carOrderBizDto,ViolationBeanDto violationBeanDto,CarDetailBizDto carDetailBizDto) throws Exception {


        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
        BeanUtils.copyProperties(violationBeanDto,violationCreateDto);
        violationCreateDto.setCarId(carDetailBizDto.getCarId());
        violationCreateDto.setVin(carDetailBizDto.getVin());
        violationCreateDto.setFineFee(new BigDecimal(violationBeanDto.getFineFee()));
        violationCreateDto.setStatus(violationBeanDto.getStatus().byteValue());
        violationCreateDto.setEngineCode(carDetailBizDto.getEngineCode());

        //无对应的订单信息
        if(null != carOrderBizDto){
            //根据门店id查询经销商信息
            StoreDto storeDto = storeService.getStoreById(carOrderBizDto.getDeliveryStoreId());
            if(null == storeDto){
                logger.error("根据门店id查询经销商信息异常 门店Id："+ carOrderBizDto.getDeliveryStoreId());
            }
            violationCreateDto.setOrderCode(carOrderBizDto.getOrderCode());
            violationCreateDto.setDealerId(storeDto == null ? null : storeDto.getDealerId());
            violationCreateDto.setUserId(carOrderBizDto.getUserId());
        }

        int ret = carViolationService.createViolation(violationCreateDto);
        if(ret < 0){
            logger.error("新建违章信息失败,CarId:"+carDetailBizDto.getCarId());
        }
    }


    /**
     * 更新违章
     * @param carsViolationDto
     * @return
     */
    private void updateViolationById(CarsViolationDto carsViolationDto,ViolationBeanDto violationBeanDto) throws Exception {
        //不一致则更新数据库
        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
        violationCreateDto.setId(carsViolationDto.getId());
        violationCreateDto.setStatus((byte)violationBeanDto.getStatus().intValue());
        if(null != violationBeanDto.getHandlingTime() ){
            violationCreateDto.setHandlingTime(violationBeanDto.getHandlingTime());
        }
        violationCreateDto.setGmtModified(LocalDateTime.now());
        int ret = carViolationService.updateById(violationCreateDto);
        if(ret < 0){
            logger.error("更新违章信息失败,CarId:"+carsViolationDto.getCarId());
        }
    }

    /**
	 * 违章发送短信
	 * @param phone
	 * @param dto
	 */
	private void sendNote(String phone,ViolationBeanDto dto) {
		JSONObject json=new JSONObject();
	    json.put("plate", dto.getLicencePlate());
	    json.put("time", DateUtil.formatDate(dto.getRegulationTime()));
	    json.put("address", dto.getAddress());
	    json.put("violations", dto.getRegulationBehavior());
	    try {
	    	smsBizService.sendMessage(phone, SmsTemplateEnum.VIOLATION_INFORM.getValue(), json.toJSONString(), null);
		} catch (Exception e) {
			logger.error("违章发送短信失败",e);
		}
	}
	
	/**
	 * 车辆违章 钉钉发送
	 * @param type 1：违章无法查询数据 2：违章未解决管理
	 * @param map
	 */
	private void sendDingTalk(Integer type,Map<String,MessageTemplateDto> map) {
		MessageTemplateDto dto = map.get(dingTalkViolationUntreated);
		if(type == 1) {
			dto = map.get(dingTalkViolationUnableQuery);
		}
		if(null == dto) {
			return;
		}
		String body = dto.getBody();
		if(StringUtils.isNoneBlank(body)) {
			DingTalkUtil.execute(dingTalkViolationUrl, body);
		}
	}
	
	/**
	 * 车辆违章提醒消息推送
	 * @param userId
	 * @param phone
	 * @param violationDto
	 */
	private void sendPush(Integer userId,String phone,ViolationBeanDto violationDto) {
		try {
			Map<String, MessageTemplateDto> map = getPushByKeys();
			if(null != map) {
				//psuh
				NotifyPushCreateDto notifyPush = getNotifyPush(phone,map,violationDto);
				notifyPushService.notifyPushByAlias(notifyPush);
				//保存站内信息
				MessageCenterCreateDto messageCenter = getMessageCenter(userId,map,violationDto);
				messageCenterService.createMessageCenter(messageCenter);
			}
		} catch (Exception e) {
			logger.error("车辆违章提醒消息推送失败",e);
		}
	}



    //region 违章无法查询邮件 Start ****************************************************

    /**
     * 违章无法查询参数拼接
     * @return
     */
    private ViolationUnableDto toViolationUnableDto(CarDetailBizDto carDetailBizDto, CarOrderBizDto carOrderBizDto) {
        ViolationUnableDto violationUnableDto = new ViolationUnableDto();
        violationUnableDto.setLicencePlate(carDetailBizDto.getLicencePlate());
        if(null != carOrderBizDto){
            UserDto userDto = userService.getUser(carOrderBizDto.getUserId());
            if(null == userDto){
                logger.error("查询用户信息为空userId："+carOrderBizDto.getUserId());
                return violationUnableDto;
            }
            violationUnableDto.setOrderCode(carOrderBizDto.getOrderCode());
            violationUnableDto.setUserName(userDto.getRealName());
            violationUnableDto.setUserPhone(userDto.getPhone());
        }
	    return violationUnableDto;
    }

    /**
     * 发送邮件
     * @param type 1：违章无法查询数据
     * @param map
     */
    private void sendUnableEmail(Integer type,Map<String,MessageTemplateDto> map,List<ViolationUnableDto> list) {
        MessageTemplateDto dto = map.get(emailViolationUnableQuery);
        if(null == dto) {
            return;
        }
        try {
            String subject = dto.getSubject();
            String body = dto.getBody();
            if(StringUtils.isNoneBlank(subject) && StringUtils.isNoneBlank(body)) {
                subject= subject.replace("${date}", DateUtil.formatDate(LocalDate.now()));
                List<String> emailTo = getEmail(type);
                String fileName = subject + ".xlsx";
                ByteArrayInputStream is = toUnableExcel(list);
                EmailUtil.sendMail(emailAccount, emailPassword, subject,body,emailTo,fileName,is);
            }
        } catch (Exception e) {
            logger.error("发送邮件异常",e);
        }
    }

    /**
     * 生成违章无法查询Excel
     * @param list
     */
    private ByteArrayInputStream toUnableExcel(List<ViolationUnableDto> list){
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream is = null;
        try {
                List<String> titles =new  ArrayList<>();
                titles.add(0, "订单号");
                titles.add(1, "车牌号");
                titles.add(2, "用户姓名");
                titles.add(3, "联系电话");
                List<List<String>> params=new ArrayList<>();
                for (ViolationUnableDto dto : list) {
                    List<String> contents=new ArrayList<>();
                    if(null != dto.getOrderCode()){
                        contents.add(0,dto.getOrderCode().toString());
                    }else{
                        contents.add(0,"-");
                    }
                    contents.add(1,dto.getLicencePlate());
                    if(null != dto.getUserName()){
                        contents.add(2,dto.getUserName());
                    }else{
                        contents.add(2,"-");
                    }
                    if(null != dto.getUserPhone()){
                        contents.add(3,dto.getUserPhone());
                    }else{
                        contents.add(3,"-");
                    }
                    params.add(contents);
                }
                XSSFWorkbook createXSSFWorkbook = PoiExcelUtils.createXSSFWorkbook(titles, params);
                baos = new ByteArrayOutputStream();
                createXSSFWorkbook.write(baos);
                baos.flush();
                is = new ByteArrayInputStream(baos.toByteArray());

        } catch (Exception e) {
            logger.error("违章无法查询的车辆发送邮件异常:", e);
        }finally {
            if(null!= baos) {
                try {
                    baos.close();
                } catch (IOException e) {

                }
            }
        }
        return is;
    }
    //endregion 违章无法查询 END ****************************************************


    //region 违章未解决邮件 Start ****************************************************
    /**
     * 违章未解决 邮件附件数据组装
     * @param carDetailBizDto
     * @param violationBeanDto
     * @param carOrderBizDto
     * @param userDto
     * @return
     */
    private ViolationUntreatedDto toViolationUntreatedDto(CarDetailBizDto carDetailBizDto, ViolationBeanDto violationBeanDto, CarOrderBizDto carOrderBizDto, UserDto userDto) {
        ViolationUntreatedDto violationUntreatedDto = new ViolationUntreatedDto();

        violationUntreatedDto.setLicencePlate(carDetailBizDto.getLicencePlate());
        violationUntreatedDto.setVin(carDetailBizDto.getVin());
        violationUntreatedDto.setRegulationBehavior(violationBeanDto.getRegulationBehavior());
        if(StringUtils.isNotBlank(violationBeanDto.getCityName())){
            violationUntreatedDto.setCityName(violationBeanDto.getCityName());
        }
        violationUntreatedDto.setAddress(violationBeanDto.getAddress());
        violationUntreatedDto.setRegulationTime(violationBeanDto.getRegulationTime());
        violationUntreatedDto.setFineFee(violationBeanDto.getFineFee());
        violationUntreatedDto.setRegulationScore(violationBeanDto.getRegulationScore());
        violationUntreatedDto.setStatus(violationBeanDto.getStatus());
        if(null != carOrderBizDto){
            violationUntreatedDto.setOrderCode(carOrderBizDto.getOrderCode());
        }
        if(null != userDto){
            violationUntreatedDto.setUserName(userDto.getRealName());
            violationUntreatedDto.setUserPhone(userDto.getPhone());
        }

        violationUntreatedDto.setQueryTime(DateUtil.formatDate(LocalDateTime.now()));

        return violationUntreatedDto;

    }


    /**
     * 无法查询的车辆 查询违章表 组装信息
     * @param carDetailBizDto
     * @param carsUnableViolationDto
     * @return
     */
    private ViolationUntreatedDto toViolationUntreatedDto(CarDetailBizDto carDetailBizDto, CarsViolationDto carsUnableViolationDto) {
        ViolationUntreatedDto violationUntreatedDto = new ViolationUntreatedDto();
        violationUntreatedDto.setLicencePlate(carDetailBizDto.getLicencePlate());
        violationUntreatedDto.setVin(carDetailBizDto.getVin());
        violationUntreatedDto.setRegulationBehavior(carsUnableViolationDto.getRegulationBehavior());
        if(StringUtils.isNotBlank(carsUnableViolationDto.getCityName())){
            violationUntreatedDto.setCityName(carsUnableViolationDto.getCityName());
        }
        violationUntreatedDto.setAddress(carsUnableViolationDto.getAddress());
        violationUntreatedDto.setRegulationTime(carsUnableViolationDto.getRegulationTime());
        violationUntreatedDto.setFineFee(carsUnableViolationDto.getFineFee().toString());
        violationUntreatedDto.setRegulationScore(carsUnableViolationDto.getRegulationScore());
        violationUntreatedDto.setStatus(carsUnableViolationDto.getStatus().intValue());
        if(null != carsUnableViolationDto.getOrderCode()){
            violationUntreatedDto.setOrderCode(carsUnableViolationDto.getOrderCode());

            OrderBizDto orderBizDto = orderBizService.getOrder(carsUnableViolationDto.getOrderCode());
            if(null == orderBizDto){
                logger.error("查询订单信息为空userId："+ carsUnableViolationDto.getOrderCode());
            }

            UserDto userDto = userService.getUser(orderBizDto.getUserId());
            if(null == userDto){
                logger.error("查询用户信息为空userId："+orderBizDto.getUserId());
            }

            violationUntreatedDto.setUserName(userDto.getRealName());
            violationUntreatedDto.setUserPhone(userDto.getPhone());
        }
        violationUntreatedDto.setQueryTime(DateUtil.formatDate(LocalDateTime.now()));

        return violationUntreatedDto;
    }


    /**
     * 发送邮件
     * @param type 2：违章未解决管理
     * @param map
     */
    private void sendUntreatedEmail(Integer type,Map<String,MessageTemplateDto> map,List<ViolationUntreatedDto> list) {
        MessageTemplateDto dto = map.get(emailViolationUntreated);
        if(null == dto) {
            return;
        }
        try {
            String subject = dto.getSubject();
            String body = dto.getBody();
            if(StringUtils.isNoneBlank(subject) && StringUtils.isNoneBlank(body)) {
                subject= subject.replace("${date}", DateUtil.formatDate(LocalDate.now()));
                List<String> emailTo = getEmail(type);
                String fileName = subject + ".xlsx";
                ByteArrayInputStream is = toUntreatedExcel(list);
                EmailUtil.sendMail(emailAccount, emailPassword, subject,body,emailTo,fileName,is);
            }
        } catch (Exception e) {
            logger.error("发送邮件异常",e);
        }
    }


    /**
     * 生成违章未解决管理Excel
     * @param list
     */
    private ByteArrayInputStream toUntreatedExcel(List<ViolationUntreatedDto> list){
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream is = null;
        try {
            List<String> titles =new  ArrayList<>();
            titles.add(0, "车牌号");
            titles.add(1, "车架号");
            titles.add(2, "违章行为");
            titles.add(3, "城市");
            titles.add(4, "违章地址");
            titles.add(5, "违章时间");
            titles.add(6, "罚款");
            titles.add(7, "扣分");
            titles.add(8, "违章状态");
            titles.add(9, "订单号");
            titles.add(10, "用户姓名");
            titles.add(11, "联系电话");
            titles.add(12, "查询日期");

            List<List<String>> params=new ArrayList<>();
            for (ViolationUntreatedDto dto : list) {
                List<String> contents=new ArrayList<>();
                contents.add(0,dto.getLicencePlate());
                contents.add(1,dto.getVin());
                contents.add(2,dto.getRegulationBehavior());
                if(StringUtils.isNotBlank(dto.getCityName())){
                    contents.add(3,dto.getCityName());
                }else{
                    contents.add(3,"-");
                }
                contents.add(4,dto.getAddress());
                contents.add(5,DateUtil.formatTime(dto.getRegulationTime()));
                contents.add(6,dto.getFineFee());
                contents.add(7,dto.getRegulationScore().toString());
                contents.add(8,CarViolationEnum.getName(dto.getStatus()));
                if(null != dto.getOrderCode()){
                    contents.add(9,dto.getOrderCode().toString());
                }else{
                    contents.add(9,"-");
                }
                if(null != dto.getUserName()){
                    contents.add(10,dto.getUserName());
                }else{
                    contents.add(10,"-");
                }
                if(null != dto.getUserPhone()){
                    contents.add(11,dto.getUserPhone());
                }else{
                    contents.add(11,"-");
                }
                contents.add(12,dto.getQueryTime());
                params.add(contents);
            }
            XSSFWorkbook createXSSFWorkbook = PoiExcelUtils.createXSSFWorkbook(titles, params);
            baos = new ByteArrayOutputStream();
            createXSSFWorkbook.write(baos);
            baos.flush();
            is = new ByteArrayInputStream(baos.toByteArray());

        } catch (Exception e) {
            logger.error("违章未解决的车辆发送邮件异常:", e);
        }finally {
            if(null!= baos) {
                try {
                    baos.close();
                } catch (IOException e) {

                }
            }
        }
        return is;
    }
    //endregion 违章未解决 END ****************************************************

    /**
     * 获取邮件人信息
     * type 1：违章无法查询数据 2：违章未解决管理
     * @return
     */
    private List<String> getEmail(Integer type){
        List<RiskEmailDto> riskList = new ArrayList<>();
        if(type == 1){
            riskList = riskEmailService.getByType(RiskEmailTypeEnum.VIOLATION_UNABLE_QUERY.getValue(),RiskEmailReceiveTypeEnum.EMAIL_RECIPIENT.getValue());
        }else{
            riskList = riskEmailService.getByType(RiskEmailTypeEnum.VIOLATION_UNTREATED.getValue(),RiskEmailReceiveTypeEnum.EMAIL_RECIPIENT.getValue());
        }
        List<String> list=null;
        if(null != riskList && !riskList.isEmpty()) {
            list=new ArrayList<>();
            for (RiskEmailDto dto : riskList) {
                list.add(dto.getEmail());
            }
        }
        return list;
    }







	/**
	 * 获取instation实体
	 * @param userId
	 * @param violationDto
	 * @param map
	 * @return
	 */
	private MessageCenterCreateDto getMessageCenter(Integer userId,Map<String,MessageTemplateDto> map,ViolationBeanDto violationDto) {
		MessageCenterCreateDto dto =new MessageCenterCreateDto();
		dto.setUserId(userId);
		MessageTemplateDto messageTemplateDto = map.get(instationViolationRemind);
		dto.setTitle(messageTemplateDto.getSubject());
		String body = messageTemplateDto.getBody();
		LocalDateTime regulationTime = violationDto.getRegulationTime();
		String violationTime = DateUtil.formatTime(regulationTime);
		body = body.replace("${licencePlate}", violationDto.getLicencePlate()).
				replace("${violationTime}",violationTime).
				replace("${violationAddress}", violationDto.getAddress()).
				replace("${violationBehavior}", violationDto.getRegulationBehavior());
		dto.setMessage(body);
		dto.setType(MessageCenterTypeEnum.VIOLATION_REMINDER.getValue());
		dto.setStatus(MessageCenterStatusEnum.UNREAD.getValue());
		return dto;
	}
	
	/**
	 * 获取psuh实体
	 * @param phone
	 * @param map
	 * @param violationDto
	 * @return
	 */
	private NotifyPushCreateDto getNotifyPush(String phone,Map<String,MessageTemplateDto> map,ViolationBeanDto violationDto) {
		NotifyPushCreateDto dto =new NotifyPushCreateDto();
		ArrayList<String> alias = new ArrayList<>(1);
		alias.add(phone);
		dto.setAlias(alias);
		MessageTemplateDto messageTemplateDto = map.get(pushViolationRemind);
		dto.setNotifyTitle(messageTemplateDto.getSubject());
		dto.setMsgTitle(messageTemplateDto.getSubject());
		String body = messageTemplateDto.getBody();
		body = body.replace("${licencePlate}", violationDto.getLicencePlate());
		dto.setIosMsgContent(body);
		dto.setAndroidMsgContent(body);
		return dto;
	}
	
	/**
	 * 查询模板信息
	 * @return
	 */
	private Map<String,MessageTemplateDto> getPushByKeys(){
		List<String> keys= new ArrayList<>();
	    keys.add(pushViolationRemind);
	    keys.add(instationViolationRemind);
	    try {
	    	 Map<String,MessageTemplateDto> map = messageTemplateService.getByKey(keys);
	    	 return map;
		} catch (Exception e) {
			logger.error("查询消息模板异常",e);
			return null;
		}
	}
	
	/**
	 * 查询模板信息
	 * @return
	 */
	private Map<String,MessageTemplateDto> getDingAndEmailByKeys(){
		List<String> keys= new ArrayList<>();
	    keys.add(dingTalkViolationUnableQuery);
	    keys.add(dingTalkViolationUntreated);
        keys.add(emailViolationUnableQuery);
        keys.add(emailViolationUntreated);
	    try {
	    	 Map<String,MessageTemplateDto> map = messageTemplateService.getByKey(keys);
	    	 return map;
		} catch (Exception e) {
			logger.error("查询消息模板异常",e);
			return null;
		}
	}




    //region 大客户违章 Start ****************************************************

    /**
     * 大客户违章数据查询
     * @return
     * @throws Exception
     */
    @Override
    public Boolean getCarViolationKeyCustomersHandler() throws Exception {
        //查询所有大客户车辆
        List<CarDto> carDtoList = carService.getCarsByBusinessType(CarsBusinessTypeEnum.KEY_ACCOUNT);
        if(null == carDtoList || carDtoList.size() <=0){
            return true;
        }

        //1大客户违章无法查询isList
        List<ViolationUnableKeyCustomersDto> unableKeyCustomersQueryList = new ArrayList<>();
        //2大客户违章未解决isList
        List<ViolationUntreatedKeyCustomersDto> untreatedKeyCustomersList = new ArrayList<>();
        //查询模板信息
        Map<String,MessageTemplateDto> dingAndEmailByKeys = getDingAndEmailByKeys();

        //查询违章
        for (CarDto carDto:carDtoList) {
            CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carDto.getId());
            if(null == carDetailBizDto){
                logger.error("查询车辆信息为空");
            }
            //查询车辆是否违章
            ResponseResult<List<ViolationBeanDto>> result = clxBizService.getCxyViolation(carDetailBizDto.getLicencePlate(),carDetailBizDto.getVin(),carDetailBizDto.getEngineCode());

            //状态码为1008表示有违章
            if(VIOLATION_CODE.equals(result.getCode())){

                for (ViolationBeanDto violationBeanDto:result.getData()) {
                    //状态为待处理或待缴费发送提醒
                    if(!CarViolationEnum.NOT_RENT.getValue().equals(violationBeanDto.getStatus())){
                        //以邮件形式向客服人员发送违章未处理信息；
                        //违章未解决 数据组装
                        untreatedKeyCustomersList.add(toViolationUntreatedKeyCustomersDto(carDetailBizDto,violationBeanDto));
                    }
                }


            }else if(result.getCode().equals(1002) || result.getCode().equals(1006) || result.getCode().equals(1007) || result.getCode().equals(1010)){
                // 违章无法查询数据
                unableKeyCustomersQueryList.add(toViolationUnableKeyCustomersDto(carDetailBizDto));
            }

        }

        if(unableKeyCustomersQueryList.size() > 0){
            //违章无法查询数据 发送邮件
            sendUnableKeyCustomersEmail(1,dingAndEmailByKeys,unableKeyCustomersQueryList);
            //发送钉钉 违章无法查询数据
            DingTalkUtil.execute(dingTalkViolationUrl, "附件为无法查询的车辆，请介入进一步处理。(大客户)");
        }

        if(untreatedKeyCustomersList.size() > 0){
            //违章未解决 发送邮件
            sendUntreatedKeyCustomersEmail(2,dingAndEmailByKeys,untreatedKeyCustomersList);
            //发送钉钉 违章未解决数据
            DingTalkUtil.execute(dingTalkViolationUrl, "附件为车辆违章未处理记录，请介入进一步处理。(大客户)");
        }

        return true;
    }



    /**
     * 大客户发送邮件
     * @param type 1：大客户违章无法查询数据
     * @param map
     */
    private void sendUnableKeyCustomersEmail(Integer type,Map<String,MessageTemplateDto> map,List<ViolationUnableKeyCustomersDto> list) {
        MessageTemplateDto dto = map.get(emailViolationUnableQuery);
        if(null == dto) {
            return;
        }
        try {
            String subject = dto.getSubject();
            String body = dto.getBody();
            if(StringUtils.isNoneBlank(subject) && StringUtils.isNoneBlank(body)) {
                subject= subject.replace("${date}", DateUtil.formatDate(LocalDate.now())) + "(大客户)";
                List<String> emailTo = getEmail(type);
                String fileName = subject + ".xlsx";
                ByteArrayInputStream is = toUnableKeyCustomersExcel(list);
                EmailUtil.sendMail(emailAccount, emailPassword, subject,body,emailTo,fileName,is);
            }
        } catch (Exception e) {
            logger.error("发送邮件异常",e);
        }
    }

    /**
     * 生成大客户违章无法查询Excel
     * @param list
     */
    private ByteArrayInputStream toUnableKeyCustomersExcel(List<ViolationUnableKeyCustomersDto> list) {
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream is = null;
        try {
            List<String> titles =new  ArrayList<>();
            titles.add(0, "车牌号");
            titles.add(1, "车架号");
            titles.add(2, "查询日期");
            List<List<String>> params=new ArrayList<>();
            for (ViolationUnableKeyCustomersDto dto : list) {
                List<String> contents=new ArrayList<>();
                contents.add(0,dto.getLicencePlate());
                contents.add(1,dto.getVin());
                contents.add(2,dto.getQueryTime());
                params.add(contents);
            }
            XSSFWorkbook createXSSFWorkbook = PoiExcelUtils.createXSSFWorkbook(titles, params);
            baos = new ByteArrayOutputStream();
            createXSSFWorkbook.write(baos);
            baos.flush();
            is = new ByteArrayInputStream(baos.toByteArray());

        } catch (Exception e) {
            logger.error("(大客户)违章无法查询的车辆发送邮件异常:", e);
        }finally {
            if(null!= baos) {
                try {
                    baos.close();
                } catch (IOException e) {

                }
            }
        }
        return is;
    }

    /**
     * 大客户发送邮件
     * @param type 2：大客户违章待处理数据
     * @param map
     */
    private void sendUntreatedKeyCustomersEmail(Integer type, Map<String, MessageTemplateDto> map, List<ViolationUntreatedKeyCustomersDto> list) {
        MessageTemplateDto dto = map.get(emailViolationUntreated);
        if(null == dto) {
            return;
        }
        try {
            String subject = dto.getSubject();
            String body = dto.getBody();
            if(StringUtils.isNoneBlank(subject) && StringUtils.isNoneBlank(body)) {
                subject= subject.replace("${date}", DateUtil.formatDate(LocalDate.now()))+ "(大客户)";
                List<String> emailTo = getEmail(type);
                String fileName = subject + ".xlsx";
                ByteArrayInputStream is = toUntreatedKeyCustomersExcel(list);
                EmailUtil.sendMail(emailAccount, emailPassword, subject,body,emailTo,fileName,is);
            }
        } catch (Exception e) {
            logger.error("发送邮件异常",e);
        }
    }


    /**
     * 生成大客户违章待处理Excel
     * @param list
     */
    private ByteArrayInputStream toUntreatedKeyCustomersExcel(List<ViolationUntreatedKeyCustomersDto> list) {
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream is = null;
        try {
            List<String> titles =new  ArrayList<>();
            titles.add(0, "车牌号");
            titles.add(1, "车架号");
            titles.add(2, "违章行为");
            titles.add(3, "城市");
            titles.add(4, "违章地址");
            titles.add(5, "违章时间");
            titles.add(6, "罚款");
            titles.add(7, "扣分");
            titles.add(8, "违章状态");
            titles.add(9, "查询日期");

            List<List<String>> params=new ArrayList<>();
            for (ViolationUntreatedKeyCustomersDto dto : list) {
                List<String> contents=new ArrayList<>();
                contents.add(0,dto.getLicencePlate());
                contents.add(1,dto.getVin());
                contents.add(2,dto.getRegulationBehavior());
                if(StringUtils.isNotBlank(dto.getCityName())){
                    contents.add(3,dto.getCityName());
                }else{
                    contents.add(3,"-");
                }
                contents.add(4,dto.getAddress());
                contents.add(5,DateUtil.formatTime(dto.getRegulationTime()));
                contents.add(6,dto.getFineFee());
                contents.add(7,dto.getRegulationScore().toString());
                contents.add(8,CarViolationEnum.getName(dto.getStatus()));
                contents.add(9,dto.getQueryTime());
                params.add(contents);
            }
            XSSFWorkbook createXSSFWorkbook = PoiExcelUtils.createXSSFWorkbook(titles, params);
            baos = new ByteArrayOutputStream();
            createXSSFWorkbook.write(baos);
            baos.flush();
            is = new ByteArrayInputStream(baos.toByteArray());

        } catch (Exception e) {
            logger.error("(大客户)违章未解决的车辆发送邮件异常:", e);
        }finally {
            if(null!= baos) {
                try {
                    baos.close();
                } catch (IOException e) {

                }
            }
        }
        return is;
    }


    /**
     * 大客户违章无法查询
     * @param carDetailBizDto
     * @return
     */
    private ViolationUnableKeyCustomersDto toViolationUnableKeyCustomersDto(CarDetailBizDto carDetailBizDto) {
        ViolationUnableKeyCustomersDto violationUnableKeyCustomersDto = new ViolationUnableKeyCustomersDto();
        violationUnableKeyCustomersDto.setLicencePlate(carDetailBizDto.getLicencePlate());
        violationUnableKeyCustomersDto.setVin(carDetailBizDto.getVin());
        violationUnableKeyCustomersDto.setQueryTime(DateUtil.formatDate(LocalDateTime.now()));

        return violationUnableKeyCustomersDto;
    }

    /**
     * 大客户违章未解决
     * @param carDetailBizDto
     * @param violationBeanDto
     * @return
     */
    private ViolationUntreatedKeyCustomersDto toViolationUntreatedKeyCustomersDto(CarDetailBizDto carDetailBizDto, ViolationBeanDto violationBeanDto) {
        ViolationUntreatedKeyCustomersDto violationUntreatedKeyCustomersDto = new ViolationUntreatedKeyCustomersDto();
        violationUntreatedKeyCustomersDto.setLicencePlate(carDetailBizDto.getLicencePlate());
        violationUntreatedKeyCustomersDto.setVin(carDetailBizDto.getVin());
        violationUntreatedKeyCustomersDto.setRegulationBehavior(violationBeanDto.getRegulationBehavior());
        if(StringUtils.isNotBlank(violationBeanDto.getCityName())){
            violationUntreatedKeyCustomersDto.setCityName(violationBeanDto.getCityName());
        }
        violationUntreatedKeyCustomersDto.setAddress(violationBeanDto.getAddress());
        violationUntreatedKeyCustomersDto.setRegulationTime(violationBeanDto.getRegulationTime());
        violationUntreatedKeyCustomersDto.setFineFee(violationBeanDto.getFineFee());
        violationUntreatedKeyCustomersDto.setRegulationScore(violationBeanDto.getRegulationScore());
        violationUntreatedKeyCustomersDto.setStatus(violationBeanDto.getStatus());
        violationUntreatedKeyCustomersDto.setQueryTime(DateUtil.formatDate(LocalDateTime.now()));

        return violationUntreatedKeyCustomersDto;
    }



    //endregion 大客户 END ****************************************************

}
